from window_login import  WindowLogin
from request_protocol import RequestProtocol
from client_socket import ClientSocket
from threading import Thread
from config import *
from tkinter.messagebox import showinfo
from window_chat import WindowChat
import sys

class Client(object):
    def __init__(self):
        """初始化客户端资源"""
        # 初始化登录窗口
        self.window = WindowLogin()
        self.window.on_reset_button_clicked(self.clear_inputs)
        self.window.on_login_button_clicked(self.send_login_data)
        self.window.on_window_close_clicked(self.exit)

        #初始化聊天窗口
        self.window_chat = WindowChat()
        self.window_chat.withdraw() # 隐藏 聊天窗口
        self.window_chat.on_send_button_click(self.send_chat_data)
        self.window_chat.window_close(self.exit)

        # 创建客户端套接字
        self.client_socket = ClientSocket()

        # 初始化消息处理函数
        self.response_handle_function = {}
        # self.response_handle_function[RESPONSE_LOGON_RESULT] = self.response_login_handle
        # self.response_handle_function[RESPONSE_CHAT] = self.response_chat_handle
        # 将上面的再精简一下
        self.register(RESPONSE_LOGON_RESULT, self.response_login_handle)
        self.register(RESPONSE_CHAT, self.response_chat_handle)

        # 初始化用户名称
        self.username = None

        # 程序正在运行的标记
        self.is_running = True

    def register(self, request_id, handle_function):
        """注册消息和消息对应的方法到字典"""
        self.response_handle_function[request_id] = handle_function

    def startup(self):
        """开启窗口"""
        self.client_socket.connect()
        Thread(target=self.response_handle).start() # 创建并开启一个子线程
        self.window.mainloop()

    def clear_inputs(self):
        """清空窗口内容"""
        self.window.clear_username()
        self.window.clear_password()

    def send_login_data(self):
        """发送信息"""
        # 获取账号密码
        username = self.window.get_username()
        password = self.window.get_password()
        # 生成协议文本
        request_text = RequestProtocol.request_login_result(username, password)
        # 发送给服务器
        print(request_text)
        self.client_socket.send_data(request_text)
        # recv_data = self.client_socket.recv_data()
        # print(recv_data)

    def send_chat_data(self):
        """获取输入框内容，发送到服务器"""
        message = self.window_chat.get_input()
        print(f'{message}')
        self.window_chat.clear_input() # 清空输入框
        # 拼接协议文本
        request_text = RequestProtocol.request_chat_result(self.username, message)
        # 发送到服务器
        self.client_socket.send_data(request_text)

        #把消息显示在聊天区
        self.window_chat.append_message('本机',message)

    def response_handle(self):
        """处理不断接收服务器的新消息"""
        while self.is_running:
            # 获取服务器消息
            recv_data = self.client_socket.recv_data()
            print(f'接收到的消息`{recv_data}`')
            # 解析消息内容
            response_data = self.parse_response_data(recv_data)
            # 根据消息内容分别进行处理
            # if response_data['response_id'] == RESPONSE_LOGON_RESULT:
            #     self.response_login_handle(response_data)
            # elif response_data['response_id'] == RESPONSE_CHAT:
            #     self.response_chat_handle(response_data)
            # 根据事件类型获取对应的方法进行调用 -- 将上面的修改为更易扩展的 若有新增的 直接加 键值对 在初始化里面进行匹配 关系是不变的
            handle_function = self.response_handle_function[response_data['response_id']]
            if handle_function:
                handle_function(response_data)

    @staticmethod
    def parse_response_data(recv_data):
        """
        登录的响应消息：1001|成功|失败|昵称|账号
        聊天的响应消息：1002|发送者昵称|消息内容
        :return:
        """
        # 使用协议约定的符号来切割消息
        response_data_list = recv_data.split(DELIMITER)

        # 解析消息的各个组成部分
        response_data = dict()
        response_data['response_id'] = response_data_list[0]

        if response_data['response_id'] == RESPONSE_LOGON_RESULT:
            """登录结果的响应"""
            response_data['result'] = response_data_list[1]
            response_data['nickname'] = response_data_list[2]
            response_data['username'] = response_data_list[3]
        elif response_data['response_id'] == RESPONSE_CHAT:
            """聊天的响应"""
            response_data['nickname'] = response_data_list[1]
            response_data['message'] = response_data_list[2]

        return response_data

    def response_login_handle(self,response_data):
        """登录结果响应"""
        print(f'接收到登录消息{response_data}')
        result = response_data['result']
        if result == '0':
            print('登录失败')
            showinfo('提示信息','登录失败，账号或密码错误！') # showinfo表示弹窗
            return
        # 登录成功获取用户信息
        showinfo('提示信息', '登录成功！')
        nickname = response_data['nickname']
        self.username = response_data['username'] # 保存在线登录的用户
        # print(f'{username}的昵称为{nickname}已经登录成功')
        #显示聊天窗口
        self.window_chat.set_title(nickname)
        self.window_chat.update()
        self.window_chat.deiconify()
        #隐藏登录窗口
        self.window.withdraw()

    def response_chat_handle(self, response_data):
        """聊天信息的响应"""
        print(f'接收到聊天信息{response_data}')
        sender = response_data['nickname']
        message = response_data['message']

        self.window_chat.append_message(sender, message)

    def exit(self):
        """退出程序"""
        self.is_running = False # 停止子线程
        self.client_socket.close() # 关闭套接字
        sys.exit(0) # 退出程序 释放资源


if __name__ == '__main__':
    client = Client()
    client.startup()